#include "EnemyDatabase.h"

#include "Conversions.h"
#include "Logger.h"
#include "Singleton.h"
#include <TinyXML\tinyxml.h>

bool EnemyDatabase::initialised = false;
EnemyDatabase EnemyDatabase::instance = EnemyDatabase();

void EnemyDatabase::initialise(const std::string& saveName)
{
    if(!initialised)
    {
        BEGIN_INITIALISATION("EnemyDatabase");

        // load enemies from file
        instance.readFile(saveName);

        END_INITIALISATION("EnemyDatabase");
    }
}

EnemyDatabase& EnemyDatabase::get()
{
    GET_INSTANCE("EnemyDatabase");
}

void EnemyDatabase::cleanUp()
{
    BEGIN_CLEAN_UP("EnemyDatabase");

    instance.enemies.clear();

    END_CLEAN_UP("EnemyDatabase");
}

const EnemyData& EnemyDatabase::getEnemyData(int id) const
{
    const_enemy_it it = enemies.find(id);
    if(it == enemies.end())
    {
        throw std::runtime_error("Couldn't find enemy with ID of " +
            Conversions::toString(id) + " in EnemyDatabase.");
    }
	return it->second;
}

void EnemyDatabase::addEnemyData(const EnemyData& enemyData, int id)
{
	enemies.insert(std::pair<int, EnemyData>(id, enemyData));
}

EnemyDatabase::EnemyDatabase()
{
}

bool EnemyDatabase::readFile( std::string saveName )
{
    TiXmlDocument edDoc("xml/" + saveName + "/EnemyDatabase.xml");
    if (!edDoc.LoadFile())
    {
        throw std::runtime_error("xml/" + saveName + "/EnemyDatabase.xml can not be opened.");
        return false;
    }
    TiXmlElement* edbElement = edDoc.RootElement();
    TiXmlElement* edatasElement = edbElement->FirstChildElement("EnemyDatas");
    TiXmlElement* edataElement = edatasElement->FirstChildElement("EnemyData");
    for(edataElement; edataElement; edataElement = edataElement->NextSiblingElement())
    {
        int id, imageId, healthMax;
        edataElement->QueryIntAttribute("id", &id);
        edataElement->QueryIntAttribute("imageId", &imageId);
        edataElement->QueryIntAttribute("healthMax", &healthMax);
        addEnemyData(EnemyData(imageId, healthMax), id);
    }  
    return true;
}

void EnemyDatabase::writeFile( std::string saveName ) const
{
    //Document
    TiXmlDocument edDoc;
    //Declaration
    TiXmlDeclaration* declaration = new TiXmlDeclaration("1.0", "", "");
    edDoc.LinkEndChild(declaration);
    //Root
    TiXmlElement* edbElement = new TiXmlElement("ENEMY_DATABASE");
    edDoc.LinkEndChild(edbElement);
    //ItemDatas
    TiXmlElement* enemyDatasElement = new TiXmlElement("EnemyDatas");
    edbElement->LinkEndChild(enemyDatasElement);
    //Adding each item data to xml
    for (enemy_map::const_iterator item = enemies.begin();item != enemies.end(); ++item)
    {
        TiXmlElement* edataElement = new TiXmlElement("EnemyData");
        edataElement->SetAttribute("id", item->first);
        edataElement->SetAttribute("imageId", item->second.getImageId());
        edataElement->SetAttribute("healthMax", item->second.getHealthMax());
        enemyDatasElement->LinkEndChild(edataElement);
    }
    //Save final xml file
    edDoc.SaveFile("xml/" + saveName + "/EnemyDatabase.xml");
}

void EnemyDatabase::save(std::string saveName)
{
    writeFile(saveName);
}
